import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import java.io.DataInput;
import java.io.DataOutput;
import org.apache.hadoop.io.Writable;
import java.io.IOException;
import org.apache.hadoop.io.WritableUtils;
import java.util.*;


public class Node implements Writable {

//  private Node suffixNode; //suffix link to the next smallest suffix.
  private Map<Character, Edge> edges;
  private int name;

  public void readFields(DataInput in) throws IOException {
    name = WritableUtils.readVInt(in);
    int size = WritableUtils.readVInt(in);
    for (int i = 0; i < size; i++) {
      int ch = WritableUtils.readVInt(in);
      Edge edge = new Edge(this);
      edge.readFields(in);
      addEdge(Character.forDigit(ch,10), edge);
    }
  }

  public void write(DataOutput out) throws IOException {
    WritableUtils.writeVInt(out, name); //the name
    WritableUtils.writeVInt(out, edges.size()); //how biggie is the mappy?
    for (Character tmpChar: getKeys()) {
      WritableUtils.writeVInt(out, Character.digit(tmpChar,10)); //this assumes character is number!!!
      edges.get(tmpChar).write(out);
    }
  }

  public int getName() {
    return name;
  }

  public Node(Map<Character, Edge> map, int name) {
    this.edges.putAll(map);
    this.name = name;
  }

  public Node() {
    edges = new HashMap<Character, Edge>();
  }

  public Node(int name) {
    this.name = name;
    edges = new HashMap<Character, Edge>();
  }

/*  public Node(Node node) {
    this(node.suffixTree);
  }


  public Node(SuffixTree suffixTree) {
    this.suffixTree = suffixTree;
    name = suffixTree.getNewNodeNumber();
    edges = new HashMap<Character, Edge>();
  }*/

  public void setName(int name) {
    this.name = name;
  }

/*  public void getNewName() {
    name=suffixTree.getNewNodeNumber();
  }*/
  
/*  public char charAt(int index) { //OBSOLETE
    return suffixTree.getText().charAt(index);
  }*/

  public void addEdge(char charIndex, Edge edge) { //merging is more straightforward if a character is given instead on an index number
      edges.put(charIndex, edge);
  }

  //public void removeEdge(int charIndex) {
  public void removeEdge(char charIndex) {
    //edges.remove(charAt(charIndex));
    edges.remove(charIndex);
  }

  public Edge findEdge(char ch) {
    return edges.get(ch);
  }

/*  public SuffixTree getSuffixTree() {
    return suffixTree;
  }*/

/*  public void setSuffixTree(SuffixTree sf) {
    this.suffixTree = sf;
  }*/

  public Collection<Edge> getEdges() { //replace name with getValues
    return edges.values();
  }

  public int getSize() {
    return edges.size();
  }

  public Collection<Character> getKeys() { //why is this a collection and not a set?
    return edges.keySet();
 }

  public boolean containsKey(Character key) {
    return edges.containsKey(key);
  }

  public void dumpNode() {
    for (char key: getKeys()) {
      System.out.println(key + " -> " + edges.get(key));
    }
  }

  @Override
    public String toString() {
      return ((Integer) name).toString();
    }
}
